package com.yao.mall.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.mall.common.ErrorCode;
import com.yao.mall.common.IdRequest;
import com.yao.mall.common.UserHolder;
import com.yao.mall.config.BusinessException;
import com.yao.mall.mapper.*;
import com.yao.mall.model.dto.GoodsSkuRequest;
import com.yao.mall.model.dto.goods.GoodsAddRequest;
import com.yao.mall.model.dto.goods.GoodsQueryRequest;
import com.yao.mall.model.dto.goods.GoodsRequest;
import com.yao.mall.model.dto.goods.HotGoodsRequest;
import com.yao.mall.model.dto.goodsAdd.*;
import com.yao.mall.model.entity.*;
import com.yao.mall.model.vo.*;
import com.yao.mall.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static com.yao.mall.constant.CommonConstant.FALSE;

/**
 * @author jiahua.yao
 * @description 针对表【goods】的数据库操作Service实现
 * @date 2024-03-07 16:45:19
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
        implements GoodsService {
    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private GoodsSkuMapper goodsSkuMapper;

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private BrandMapper brandMapper;

    @Resource
    private SpuImageMapper spuImageMapper;

    @Resource
    private SkuImageService skuImageService;
    @Resource
    private SkuAttrValueService skuAttrValueService;

    @Resource
    private GoodsSkuService goodsSkuService;

    @Resource
    private SpuAttrValueMapper spuAttrValueMapper;

    @Resource
    private SkuAttrValueMapper skuAttrValueMapper;

    @Override
    //todo 列表根据选择的sortField筛选不同条件下应该显示的商品
    public Page<GoodsBasicVO> getGoodsBasic(GoodsQueryRequest goodsQueryRequest) {
        long current = goodsQueryRequest.getCurrent();
        long pageSize = goodsQueryRequest.getPageSize();
        QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
        Long categoryId = goodsQueryRequest.getCategoryId();
        String goodsName = goodsQueryRequest.getGoodsName();
        if (StringUtils.isNotBlank(goodsName)) {
            goodsQueryWrapper.like("name", goodsName);
        }
        if (categoryId != null) {
            //根据子类id查询
            goodsQueryWrapper.eq("category_id", categoryId);
        }
        // 商品必须是上架的商品,1-已上架
        if (UserHolder.getUser() == null || UserHolder.getUser().getUserPower().equals("0")) {
            goodsQueryWrapper.eq("spu_status", "1");
        }
        Page<Goods> goodsRecords = this.page(new Page<>(current, pageSize), goodsQueryWrapper);
        List<Goods> records = goodsRecords.getRecords();
        List<GoodsBasicVO> goodsBasicVOList = toGoodsBasicVO(records);
        PageDTO<GoodsBasicVO> goodsBasicVOPageDTO = new PageDTO<>(goodsRecords.getCurrent(), goodsRecords.getSize(), goodsRecords.getTotal());
        goodsBasicVOPageDTO.setRecords(goodsBasicVOList);
        return goodsBasicVOPageDTO;
    }

    @Override
    public Boolean changeStatusById(GoodsRequest goodsRequest) {
        Long spuId = goodsRequest.getSpuId();
        String spuStatus = goodsRequest.getSpuStatus();
        if (goodsRequest.getSpuId() == null || StringUtils.isBlank(spuStatus)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "缺少商品信息！");
        }
        Goods goods = new Goods();
        String newSpuStatus = spuStatus.equals("0") ? "1" : "0";
        goods.setSpuStatus(newSpuStatus);
        goods.setId(spuId);
        return this.updateById(goods);
    }

    @Override
    public Boolean deleteGoods(Long id) {
        Goods goodsGet = this.getById(id);
        if (goodsGet.getSpuStatus().equals("1")) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该商品已上架，请先下架后删除！");
        }
        Goods goods = new Goods();
        goods.setId(id);
        int i = goodsMapper.deleteById(goods);
        return i > 0;
    }

    @Override
    public GoodsVO getGoodsDetails(IdRequest idRequest) {
        //1、商品基本信息查询
        Goods goods = this.getById(idRequest.getId());
        Long id = idRequest.getId();
        //2、获取商品的分类信息
        Category category = categoryMapper.selectById(goods.getCategoryId());
        Category parentCategory = categoryMapper.selectById(category.getParentId());
        SecCategoryVO secCategoryVO = new SecCategoryVO();
        BeanUtils.copyProperties(category, secCategoryVO);
        secCategoryVO.setParentName(parentCategory.getName());
        //3、获取商品的品牌信息
        Brand brand = brandMapper.selectById(goods.getBrandId());
        BrandVO brandVO = new BrandVO();
        BeanUtils.copyProperties(brand, brandVO);
        //4、获取商品的介绍图信息
        QueryWrapper<SpuImage> spuImageQueryWrapper = new QueryWrapper<>();
        spuImageQueryWrapper.eq("spu_id", id);
        List<SpuImageVO> spuImageVOList = spuImageMapper.selectList(spuImageQueryWrapper).stream().map(spuImage -> {
            SpuImageVO spuImageVO = new SpuImageVO();
            BeanUtils.copyProperties(spuImage, spuImageVO);
            return spuImageVO;
        }).toList();
        //5、获取spu商品基本属性
        QueryWrapper<SpuAttrValue> spuAttrValueQueryWrapper = new QueryWrapper<>();
        spuAttrValueQueryWrapper.eq("spu_id", id);
        List<SpuAttrValueVO> spuAttrValueVOList = spuAttrValueMapper.selectList(spuAttrValueQueryWrapper).stream().map(spuAttrValue -> {
            SpuAttrValueVO spuAttrValueVO = new SpuAttrValueVO();
            BeanUtils.copyProperties(spuAttrValue, spuAttrValueVO);
            return spuAttrValueVO;
        }).toList();

        //6、获取商品规格(sku)信息、前端显示需要的规格合集、前端默认显示的sku_image
        List<Long> keyIds = new ArrayList<>();
        List<SkuImageVO> skuImageVOS = new ArrayList<>();
        List<GoodsSkuVO> goodsSkuVOList = goodsSkuService.getGoodsSku(goods.getId(), keyIds, skuImageVOS);
        if (keyIds.isEmpty()) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        /**
         * sku的list
         */
        List<Long> skuIdList = goodsSkuVOList.stream().map(GoodsSkuVO::getId).toList();
        /*
            select distinct key_id,key_name as keyName,value from sku_attr_value
            where sku_id in(1,2,3,4) order by key_id
         */
        QueryWrapper<SkuAttrValue> skuAttrValueQueryWrapper = new QueryWrapper<>();
        skuAttrValueQueryWrapper.in("sku_id", skuIdList)// 添加in条件
                .select("DISTINCT key_id", "key_name as keyName", "value") // 指定查询列，并使用别名
                .orderByAsc("key_id"); // 排序
        List<SkuAttrValue> skuAttrValueList = skuAttrValueMapper.selectList(skuAttrValueQueryWrapper);
        List<SpecsVO> specsVOS = getSpecsVOS(skuAttrValueList);
        List<SpecsVO> sortSpecsList = specsVOS.stream().sorted(Comparator.comparing(SpecsVO::getAttrKeyId)).toList();
        //6、存入goodsVO
        //6.1 商品基本信息存入VO
        GoodsVO goodsVO = new GoodsVO();
        BeanUtils.copyProperties(goods, goodsVO);
        //6.2 分类信息存入vo
        goodsVO.setSecCategoryVO(secCategoryVO);
        //6.3 品牌信息存入VO
        goodsVO.setBrandVO(brandVO);
        //6.4 商品基本属性信息
        goodsVO.setSpuAttrValueVOList(spuAttrValueVOList);
        //6.5 商品介绍图信息
        goodsVO.setSpuImageVOList(spuImageVOList);
        //6.6.规格及图片信息存入goodsVO
        goodsVO.setGoodsSkuVOList(goodsSkuVOList);
        goodsVO.setSpecsVOList(sortSpecsList);
        //6.7 默认图片信息存入
        goodsVO.setDefalutGoodsSkuVOList(skuImageVOS);
        return goodsVO;
    }

    /**
     * 获取属性名及其对应的属性值，相同名称的值用“，”拼接，用于前端可选择规格的总规格list
     *
     * @param skuAttrValueList sku,value
     * @return list
     */
    private List<SpecsVO> getSpecsVOS(List<SkuAttrValue> skuAttrValueList) {
        HashMap<String, List<SpecsValueVO>> hashMap = new HashMap<>();
        for (SkuAttrValue skuAttrValue : skuAttrValueList) {
            String key = skuAttrValue.getKeyId() + "," + skuAttrValue.getKeyName();
            String value = skuAttrValue.getValue();
            if (!hashMap.containsKey(key)) {
                hashMap.put(key, new ArrayList<>());
            }
            SpecsValueVO specsValueVO = new SpecsValueVO();
            specsValueVO.setValue(value);
            hashMap.get(key).add(specsValueVO);
        }
        List<SpecsVO> specsVOS = new ArrayList<>();
        for (Map.Entry<String, List<SpecsValueVO>> entry : hashMap.entrySet()) {
            String[] split = entry.getKey().split(",");
            SpecsVO specsVO = new SpecsVO();
            specsVO.setAttrKeyId(Long.parseLong(split[0]));
            specsVO.setAttrName(split[1]);
            specsVO.setValueList(entry.getValue());
            specsVOS.add(specsVO);
        }
        return specsVOS;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Boolean addGoods(GoodsAddRequest goodsAddRequest) {
        checkAdd(goodsAddRequest);
        Goods goods = new Goods();
        //1、商品基本信息
        BeanUtils.copyProperties(goodsAddRequest, goods);
        //sku排序第一个第一张图片作为主图
        goods.setMainImage(goodsAddRequest.getGoodsSkuAddRequest().get(0).getSkuImageAddRequest().get(0).getImage());
        int insert = goodsMapper.insert(goods);
        if (insert <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "商品添加失败");
        }
        //1.1、spu照片信息
        List<SpuImage> goodsImageList = goodsAddRequest.getSpuImageAddRequest().stream().map(goodsImage -> {
            SpuImage goodsImageNew = new SpuImage();
            goodsImageNew.setSpuId(goods.getId());
            goodsImageNew.setImage(goodsImage.getImage());
            return goodsImageNew;
        }).toList();
        //1.2 spu基本属性信息（如手机的屏幕分辨率、内存等）
        List<SpuAttrValueAddRequest> spuAttrValuetList = goodsAddRequest.getSpuAttrValueAddRequest();
        List<SpuAttrValue> spuAttrValueList = spuAttrValuetList.stream().map(spuAttrValueAdd -> {
            SpuAttrValue spuAttrValue = new SpuAttrValue();
            spuAttrValue.setSpuId(goods.getId());
            spuAttrValue.setKeyId(spuAttrValueAdd.getKeyId());
            spuAttrValue.setKeyName(spuAttrValueAdd.getKeyName());
            spuAttrValue.setValue(spuAttrValueAdd.getValue());
            return spuAttrValue;
        }).toList();

        Boolean addSpuImage = spuImageMapper.insertBatch(goodsImageList);
        Boolean addSpuAttrValue = spuAttrValueMapper.insertBatch(spuAttrValueList);
        if (FALSE.equals(addSpuImage) || FALSE.equals(addSpuAttrValue)) {
            // 回滚，存入的goods值需要删除
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "存储图像错误，商品添加失败");
        }
        //2、规格信息，规格表，属性值表，sku照片表的添加（属性传过来的应该是个编号）
        Long spuId = goods.getId();
        List<GoodsSkuAddRequest> goodsSkuAddList = goodsAddRequest.getGoodsSkuAddRequest();
        for (GoodsSkuAddRequest goodsSkuAdd : goodsSkuAddList) {
            //2.1 存sku表
            GoodsSku goodsSku = getGoodsSku(goodsSkuAdd, spuId, goods);
            int addGoodsSku = goodsSkuMapper.insert(goodsSku);
            if (addGoodsSku <= 0) {
                // 回滚，存入的goods值需要删除
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "商品信息存储错误，商品添加失败");
            }
            //2.2 存sku属性值表
            List<SkuAttrValueAddRequest> skuAttrValueAddList = goodsSkuAdd.getSkuAttrValueAddRequest();
            List<SkuAttrValue> skuAttrValueList = skuAttrValueAddList.stream().map(skuAttrValueAdd -> {
                SkuAttrValue skuAttrValue = new SkuAttrValue();
                BeanUtils.copyProperties(skuAttrValueAdd, skuAttrValue);
                skuAttrValue.setId(null);
                skuAttrValue.setSkuId(goodsSku.getId());
                return skuAttrValue;
            }).toList();
            boolean saveBatch = skuAttrValueService.saveBatch(skuAttrValueList);
            if (!saveBatch) {
                // 回滚
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "规格信息存储错误，商品添加失败");
            }
            //2.3 存sku_image表
            List<SkuImageAddRequest> skuImageAddList = goodsSkuAdd.getSkuImageAddRequest();
            if (CollectionUtils.isEmpty(skuImageAddList)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "每件具体商品的图片信息不能为空");
            }
            List<SkuImage> skuImages = skuImageAddList.stream().map(skuImageAddRequest -> {
                SkuImage skuImage = new SkuImage();
                BeanUtils.copyProperties(skuImageAddRequest, skuImage);
                skuImage.setSkuId(goodsSku.getId());
                return skuImage;
            }).toList();
            boolean saveSkuImage = skuImageService.saveBatch(skuImages);
            if (!saveSkuImage) {
                // 回滚
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "具体商品的图片信息不能为空");
            }
        }
        return true;
    }

    @NotNull
    private static GoodsSku getGoodsSku(GoodsSkuAddRequest goodsSkuAdd, Long spuId, Goods goods) {
        GoodsSku goodsSku = new GoodsSku();
        goodsSku.setSpuId(spuId);
        goodsSku.setGoodsName(goods.getName());
        goodsSku.setSkuSort(goodsSkuAdd.getSkuSort());
        goodsSku.setSkuStatus(goodsSkuAdd.getSkuStatus());
        goodsSku.setSkuDiscount(goodsSkuAdd.getSkuDiscount());
        //商品的sku价格
        BigDecimal skuOldPrice = goodsSkuAdd.getSkuOldPrice();
        BigDecimal skuPrice = goodsSkuAdd.getSkuPrice();
        Integer stock = goodsSkuAdd.getStock();
        goodsSku.setSales(0);
        if (skuPrice == null || skuOldPrice == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "每种属性的原价和现价都不能为空");
        }
        if (stock == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "库存信息不能为空");
        }
        goodsSku.setSkuPrice(skuPrice);
        goodsSku.setSkuOldPrice(skuOldPrice);
        goodsSku.setSkuDiscount(goodsSku.getSkuDiscount());
        goodsSku.setStock(stock);
        // 暂时不设置status字段，默认添加商品后直接上架
        return goodsSku;
    }

    private static void checkAdd(GoodsAddRequest goodsAddRequest) {
        String name = goodsAddRequest.getName();
        String des = goodsAddRequest.getDes();

        /*String spuStatus = goodsAddRequest.getSpuStatus();*/
        List<GoodsSkuAddRequest> goodsSkuAddRequestList = goodsAddRequest.getGoodsSkuAddRequest();
        List<SpuImageAddRequest> spuImageAddRequestList = goodsAddRequest.getSpuImageAddRequest();
        Long brandId = goodsAddRequest.getBrandId();
        Long categoryId = goodsAddRequest.getCategoryId();
        Integer categoryParentId = goodsAddRequest.getCategoryParentId();
        BigDecimal spuPrice = goodsAddRequest.getSpuPrice();
        if (StringUtils.isAnyBlank(name, des) || CollectionUtils.isEmpty(goodsSkuAddRequestList)
                || brandId == null || categoryId == null || categoryParentId == null || spuPrice == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "存在必要参数为空");
        }
        if (CollectionUtils.isEmpty(spuImageAddRequestList)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "商品介绍图不能为空");
        }
    }

    @Override
    public List<GoodsBasicVO> toGoodsBasicVO(List<Goods> goodsList) {
        return goodsList.stream().map(goods -> {
            GoodsBasicVO goodsBasicVO = new GoodsBasicVO();
            BeanUtils.copyProperties(goods, goodsBasicVO);
            return goodsBasicVO;
        }).toList();
    }

    @Override
    public List<GoodsBasicVO> getGoods() {
        //todo 根据存储在redis中该商品的点击次数决定推荐的人气，根据更新时间推荐新鲜好物
        List<Goods> list = this.list();
        return toGoodsBasicVO(list);
    }

    @Override
    public List<GoodsBasicVO> getHotGoods(HotGoodsRequest hotGoodsRequest) {
        Integer hotType = hotGoodsRequest.getHotType();
        Long spuId = hotGoodsRequest.getSpuId();
        //1.spuId获取商品分类
        Goods goods = this.getById(spuId);
        Long categoryId = goods.getCategoryId();
        //2、从redis中获取该分类下score最高的前三位（也就是在下单中最多的商品）
        //todo 待订单接口完成后实现，现在的数据拿goods前三条
        QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
        goodsQueryWrapper.last("limit 3");
        List<Goods> goodsList = goodsMapper.selectList(goodsQueryWrapper);
        return this.toGoodsBasicVO(goodsList);
    }

    @Override
    public Boolean changeStockById(GoodsSkuRequest goodsSkuRequest) {
        Long skuId = goodsSkuRequest.getSkuId();
        Integer stock = goodsSkuRequest.getStock();
        if (skuId == null || stock == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        if (stock < 0){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"库存不能小于0");
        }
        GoodsSku goodsSku = new GoodsSku();
        goodsSku.setId(skuId);
        goodsSku.setStock(stock);
        int i = goodsSkuMapper.updateById(goodsSku);
        return i>0;
    }
}




